import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';

import { Like, Repository } from 'typeorm';

import { BusinessException } from '~/common/exceptions/biz.exception';
import { ErrorEnum } from '~/constants/error-code.constant';
import { paginate } from '~/helper/paginate';
import { Pagination } from '~/helper/paginate/pagination';
import { DictItemEntity } from '~/modules/system/dict-item/dict-item.entity';

import { DictItemDto, DictItemQueryDto } from './dict-item.dto';
import { isNil } from 'lodash';

@Injectable()
export class DictItemService {
  constructor(
    @InjectRepository(DictItemEntity)
    private dictItemRepository: Repository<DictItemEntity>
  ) {}

  /**
   * 罗列所有配置
   */
  async page({
    page,
    pageSize,
    label,
    value,
    typeId,
  }: DictItemQueryDto): Promise<Pagination<DictItemEntity>> {
    const queryBuilder = this.dictItemRepository
      .createQueryBuilder('dict_item')
      .orderBy({ orderNo: 'ASC' })
      .where({
        ...(label && { label: Like(`%${label}%`) }),
        ...(value && { value: Like(`%${value}%`) }),
        type: {
          id: typeId,
        },
      });

    return paginate(queryBuilder, { page, pageSize });
  }

  /**
   * 获取参数总数
   */
  async countConfigList(): Promise<number> {
    return this.dictItemRepository.count();
  }

  /**
   * 新增
   */
  async create(dto: DictItemDto): Promise<void> {
    const { typeId, parentId, ...rest } = dto;

    // 检查 parentId 是否存在
    if (!isNil(parentId)) {
      const parentExists = await this.dictItemRepository.findOneBy({ id: parentId });
      if (!parentExists) {
        throw new BusinessException(ErrorEnum.NOT_FOUND);
      }
    }

    await this.dictItemRepository.insert({
      ...rest,
      type: {
        id: typeId,
      },
      ...(!isNil(parentId) ? { parent: { id: parentId } } : { parent: null }),
    });
  }

  /**
   * 更新
   */
  async update(id: number, dto: Partial<DictItemDto>): Promise<void> {
    const { typeId, ...rest } = dto;
    await this.dictItemRepository.update(id, {
      ...rest,
      type: {
        id: typeId,
      },
    });
  }

  /**
   * 删除
   */
  async delete(id: number): Promise<void> {
    await this.dictItemRepository.delete(id);
  }

  /**
   * 查询单个
   */
  async findOne(id: number): Promise<DictItemEntity> {
    return this.dictItemRepository.findOneBy({ id });
  }

  async isExistKey(dto: DictItemDto): Promise<void | never> {
    const { value, typeId } = dto;
    const result = await this.dictItemRepository.findOneBy({ value, type: { id: typeId } });
    if (result) throw new BusinessException(ErrorEnum.DICT_NAME_EXISTS);
  }

  /**
   * 根据 typeId 获取所有的字典项
   * @param typeId
   */
  async getAllByTypeId(typeId: number): Promise<DictItemEntity[]> {
    return this.dictItemRepository.find({
			where: { type: { id: typeId } },
			select: ['id', 'label', 'value'],
		});
  }

  /**
   * 根据 itemId 获取所有的字典项
   * @param itemId
   */
  async getAllByItemId(itemId: number): Promise<DictItemEntity[]> {
    return this.dictItemRepository
      .createQueryBuilder('dict_item')
      .where('dict_item.item_id = :itemId', { itemId })
      .getMany();
  }

  async bindUser(userId: number, labelIds: number[]): Promise<void> {
    // 判断typeIds是否都存在
    const labelIdsExist = await this.dictItemRepository
      .createQueryBuilder('dict_item')
      .where('dict_item.id IN (:...labelIds)', { labelIds })
      .getMany();

    if (labelIdsExist.length !== labelIds.length) {
      throw new BusinessException(ErrorEnum.NOT_FOUND);
    }

    await this.dictItemRepository
      .createQueryBuilder()
      .delete()
      .from('ah_label_user')
      .where('user_id = :userId', { userId })
      .execute();

		await this.dictItemRepository
			.createQueryBuilder()
			.insert()
			.into('ah_label_user')
			.values(
				labelIds.map((labelId) => ({
					user_id: userId,
					label_id: labelId,
				}))
			)
			.execute();
  }
}
